#include "protocolmodbus.hpp"

using namespace protocols;
///>协议功能类 ：modbus
typedef struct
{
	const protocolmodbus::RegisterAttributeTPDF *tAttribute;
	bool bOutRange;
}FindResultTPDF;

const uint8_t mCRCHiTbl[] = 
{0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01,
0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81,
0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01,
0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01,
0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01,
0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
0x40};

const uint8_t mCRCLoTbl[] =
{0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7, 0x05, 0xC5, 0xC4,
0x04, 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09,
0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE, 0xDF, 0x1F, 0xDD,
0x1D, 0x1C, 0xDC, 0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,
0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32, 0x36, 0xF6, 0xF7,
0x37, 0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A,
0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, 0xEE,
0x2E, 0x2F, 0xEF, 0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, 0x61, 0xA1, 0x63, 0xA3, 0xA2,
0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F,
0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68, 0x78, 0xB8, 0xB9, 0x79, 0xBB,
0x7B, 0x7A, 0xBA, 0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,
0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0, 0x50, 0x90, 0x91,
0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C,
0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98, 0x88,
0x48, 0x49, 0x89, 0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43, 0x83, 0x41, 0x81, 0x80,
0x40};

static uint16_t dCrcCheck(unsigned char *ucData,unsigned short usLen)
{
  uint8_t ucCRCHi=0xff;
  uint8_t ucCRCLo=0xff;
  uint16_t usIndex;
  while(usLen--)
  {
    usIndex = ucCRCHi ^ (*ucData++);
    ucCRCHi = ucCRCLo ^ mCRCHiTbl[usIndex];
    ucCRCLo = mCRCLoTbl[usIndex];
  }
  return (ucCRCHi << 8 | ucCRCLo);
}

static bool FindDataType(const protocolmodbus::RegisterAttributeTPDF *tAttribute, uint16_t ustAttributeLen, FindResultTPDF *tFindResult, uint16_t usAddroffset)
{
	uint16_t i, j = 0;
	
	tFindResult->tAttribute = &tAttribute[0];
	tFindResult->bOutRange = false;
	for(i = 0; i < ustAttributeLen; i++)
	{
		if(j > usAddroffset)
		{
			tFindResult->tAttribute = &tAttribute[i - 1];
			tFindResult->bOutRange = true;
			return(true);
		}
		else if(j == usAddroffset)
		{
			tFindResult->tAttribute = &tAttribute[i];
			tFindResult->bOutRange = false;
			return(true);
		}
		switch(tAttribute[i].tVariableAttribute.tType)
		{
			case VARIABLE_TYPE_UINT32:
			case VARIABLE_TYPE_INT32:
				j += 4;
				break;
			case VARIABLE_TYPE_CHAR:
				j += tAttribute[i].tVariableAttribute.ucLen;
				break;
			default:
				j += 2;
				break;
		}
	}
	return(false);
}

void protocolmodbus::DataCopy(ModbusRegPartitionTPDF *tModbusRegPartitions, uint8_t *ucTag)
{
	uint16_t i, j, k, usAddrOffset;
	FindResultTPDF tFindResult;
	
	usAddrOffset = (RegisterAddr - tModbusRegPartitions->RegisterStartAddr) * 2;
	if(!tModbusRegPartitions->tRegisterAttribute || !tModbusRegPartitions->usRegisterAttributeLen)
	{
		for(i = 0; i < DataLen; i += 2)
		{
			ucTag[i + 1] = tModbusRegPartitions->Resource[usAddrOffset + i];
			ucTag[i] = tModbusRegPartitions->Resource[usAddrOffset + i + 1];
		}
		return;
	}
	for(i = 0; i < DataLen;)
	{
		if(!FindDataType(tModbusRegPartitions->tRegisterAttribute, tModbusRegPartitions->usRegisterAttributeLen, &tFindResult, usAddrOffset + i))
		{
			ucTag[i + 1] = tModbusRegPartitions->Resource[usAddrOffset + i];
			ucTag[i] = tModbusRegPartitions->Resource[usAddrOffset + i + 1];
			i += 2;
			continue;
		}
		switch(tFindResult.tAttribute->tVariableAttribute.tType)
		{
			case VARIABLE_TYPE_CHAR:
				j = tFindResult.tAttribute->tVariableAttribute.ucLen;
				if(j > (DataLen - i))
				{
					j = DataLen - i;
				}
				for(k = 0; k < j; k++)
				{
					ucTag[i + k] = tModbusRegPartitions->Resource[usAddrOffset + i + k];
				}
				i += j;
				break;
			case VARIABLE_TYPE_UINT32:
			case VARIABLE_TYPE_INT32:
				if(tFindResult.bOutRange)
				{
					ucTag[i + 1] = tModbusRegPartitions->Resource[usAddrOffset - 2 + i];
					ucTag[i] = tModbusRegPartitions->Resource[usAddrOffset + i - 1];
					i += 2;
				}
				else
				{
					ucTag[i + 3] = tModbusRegPartitions->Resource[usAddrOffset + i];
					ucTag[i + 2] = tModbusRegPartitions->Resource[usAddrOffset + i + 1];
					ucTag[i + 1] = tModbusRegPartitions->Resource[usAddrOffset + i + 2];
					ucTag[i] = tModbusRegPartitions->Resource[usAddrOffset + i + 3];
					if(i + 4 <= DataLen)
					{
						i += 4;
					}
					else
					{
						i += 2;
					}
				}
				break;
			default:
				ucTag[i + 1] = tModbusRegPartitions->Resource[usAddrOffset + i];
				ucTag[i] = tModbusRegPartitions->Resource[usAddrOffset + i + 1];
				i += 2;
				break;
		}
	}
}

bool protocolmodbus::DataCheckAndWriteDataParse(ModbusRegPartitionTPDF *tModbusRegPartitions)
{
	uint16_t i, j, usAddrOffset;
	int32_t k;
	FindResultTPDF tFindResult;
	WriteDataAttributeTPDF *wptr;
	
	usAddrOffset = (RegisterAddr - tModbusRegPartitions->RegisterStartAddr) * 2;
	if(!tModbusRegPartitions->tRegisterAttribute || !tModbusRegPartitions->usRegisterAttributeLen)
	{
		return(true);
	}
	usWriteDataAttributeLen = 0;
	for(i = 0; i < DataLen;)
	{
		if(!FindDataType(tModbusRegPartitions->tRegisterAttribute, tModbusRegPartitions->usRegisterAttributeLen, &tFindResult, usAddrOffset + i))
		{
			i += 2;
			wptr = &mWriteDataAttribute[usWriteDataAttributeLen];
			wptr->iKey = -1;
			wptr->ucData[0] = Data[i + 1];
			wptr->ucData[1] = Data[i];
			wptr->usLen = 2;
			wptr->usResourceOffset = i + usAddrOffset;
			usWriteDataAttributeLen++;
			if(usWriteDataAttributeLen > PROTOCOLMODBUS_MULTWRITE_REGISTERS_SURPPORT)
			{
				return(false);
			}
			continue;
		}
		switch(tFindResult.tAttribute->tVariableAttribute.tType)
		{
			case VARIABLE_TYPE_CHAR:
				j = tFindResult.tAttribute->tVariableAttribute.ucLen;
				if(j > (DataLen - i))
				{
					j = DataLen - i;
				}
				if(j >= PROTOCOLMODBUS_WRITE_REGISTERLEN_SURPPORT)
				{
					return(false);
				}
				if(!tFindResult.tAttribute->bLimitEnable)
				{
				}
				else if(tFindResult.tAttribute->CustomRegisterLimitCallBack)
				{
					if(!tFindResult.tAttribute->CustomRegisterLimitCallBack(RegisterAddr + (i >> 1), Data + i, j))
					{
						return(false);
					}
				}
				else
				{
					for(k = 0; k < j; k++)
					{
						if(!(Data[i + k] >= tFindResult.tAttribute->tVariableAttribute.tVariableDataLimit.iLower && 
							 Data[i + k] <= tFindResult.tAttribute->tVariableAttribute.tVariableDataLimit.iUpper))
						{
							return(false);
						}
					}
				}
				wptr = &mWriteDataAttribute[usWriteDataAttributeLen];
				wptr->iKey = tFindResult.tAttribute->tVariableAttribute.uiKey;
				for(k = 0; k < j; k++)
				{
					wptr->ucData[k] = Data[i + k];
				}
				wptr->usLen = j;
				wptr->usResourceOffset = i + usAddrOffset;
				usWriteDataAttributeLen++;
				if(usWriteDataAttributeLen > PROTOCOLMODBUS_MULTWRITE_REGISTERS_SURPPORT)
				{
					return(false);
				}
				i += j;
				break;
			case VARIABLE_TYPE_UINT32:
			case VARIABLE_TYPE_INT32:
				if(tFindResult.bOutRange)
				{
					return(false);
				}
				if(!tFindResult.tAttribute->bLimitEnable)
				{
				}
				else if(tFindResult.tAttribute->CustomRegisterLimitCallBack)
				{
					if(!tFindResult.tAttribute->CustomRegisterLimitCallBack(RegisterAddr + (i >> 1), Data + i, 4))
					{
						return(false);
					}
				}
				else
				{
					if(DataLen - i < 4)
					{
						return(false);
					}
					k = (Data[i] << 24) + 
					    (Data[i + 1] << 16) + 
					    (Data[i + 2] << 8) +
					    Data[i + 3];
					if(!(k >= tFindResult.tAttribute->tVariableAttribute.tVariableDataLimit.iLower && 
						 k <= tFindResult.tAttribute->tVariableAttribute.tVariableDataLimit.iUpper))
					{
						return(false);
					}
				}
				k = (Data[i] << 24) + (Data[i + 1] << 16) + (Data[i + 2] << 8) + Data[i + 3];
				wptr = &mWriteDataAttribute[usWriteDataAttributeLen];
				wptr->iKey = tFindResult.tAttribute->tVariableAttribute.uiKey;
				wptr->ucData[0] = k & 0x000000ff;
				wptr->ucData[1] = (k >> 8) & 0x000000ff;
				wptr->ucData[2] = (k >> 16) & 0x000000ff;
				wptr->ucData[3] = (k >> 24) & 0x000000ff;
				wptr->usLen = 4;
				wptr->usResourceOffset = i + usAddrOffset;
				usWriteDataAttributeLen++;
				if(usWriteDataAttributeLen > PROTOCOLMODBUS_MULTWRITE_REGISTERS_SURPPORT)
				{
					return(false);
				}
				i += 4;
				break;
			default:
				if(!tFindResult.tAttribute->bLimitEnable)
				{
				}
				else if(tFindResult.tAttribute->CustomRegisterLimitCallBack)
				{
					if(!tFindResult.tAttribute->CustomRegisterLimitCallBack(RegisterAddr + (i >> 1), Data + i, 2))
					{
						return(false);
					}
				}
				else
				{
					k = (Data[i] << 8) + Data[i + 1];
					if(!(k >= tFindResult.tAttribute->tVariableAttribute.tVariableDataLimit.iLower && 
						 k <= tFindResult.tAttribute->tVariableAttribute.tVariableDataLimit.iUpper))
					{
						return(false);
					}
				}
				wptr = &mWriteDataAttribute[usWriteDataAttributeLen];
				wptr->iKey = tFindResult.tAttribute->tVariableAttribute.uiKey;
				wptr->ucData[0] = Data[i + 1];
				wptr->ucData[1] = Data[i];
				wptr->usLen = 2;
				wptr->usResourceOffset = i + usAddrOffset;
				usWriteDataAttributeLen++;
				if(usWriteDataAttributeLen > PROTOCOLMODBUS_MULTWRITE_REGISTERS_SURPPORT)
				{
					return(false);
				}
				i += 2;
				break;
		}
	}
	return(true);
}
//基本特殊命令处理
int8_t protocolmodbus::BaseSpeOrderProcess(uint8_t ucSlaveAddr, uint16_t tCommand, uint8_t *ucData, uint16_t usLen)
{
	uint32_t i;
	
	switch(tCommand)
	{
		case 0x5000:
			if(!mFirmwaredownload)
			{
				return(-1);
			}
			if(!mFirmwaredownload->Start())
			{
				return(4);
			}
			mFirmwaredownload->FirmWareInfor.uiOldVersion = 0;
			mFirmwaredownload->FirmWareInfor.uiNewVersion = 1;
			mFirmwaredownload->FirmWareInfor.uiPackLength = 128;
			return(0);
		case 0x5001: //发送下载文件信息
			if(!mFirmwaredownload)
			{
				return(-1);
			}
			if(usLen != 16)
			{
				return(3);
			}
			mFirmwaredownload->FirmWareInfor.uiOldVersion = 0;
			mFirmwaredownload->FirmWareInfor.uiUpdateCount = 0;
			mFirmwaredownload->FirmWareInfor.uiNewVersion = ucData[1] + (ucData[0] << 8);
			mFirmwaredownload->FirmWareInfor.uiLength = ucData[7] + (ucData[6] << 8) + (ucData[5] << 16) + (ucData[4] << 24);
			mFirmwaredownload->FirmWareInfor.uiPackLength = ucData[9] + (ucData[8] << 8);
			mFirmwaredownload->FirmWareInfor.uiPrgCheckSum = ucData[13] + (ucData[12] << 8) + (ucData[11] << 16) + (ucData[10] << 24);
			return(0);
		case 0x5002:
			if(!mFirmwaredownload)
			{
				return(-1);
			}
			if(usLen < 4)
			{
				return(3);
			}
			i = ucData[3] + (ucData[2] << 8) + (ucData[1] << 16) + (ucData[0] << 24);
			if(mFirmwaredownload->WritePrg(i, ucData + 4, usLen - 4))
			{
				return(0);
			}
			else
			{
				return(4);
			}
		case 0x5003:
			if(!mFirmwaredownload->Stop())
			{
				return(4);
			}
			if(!mFirmwaredownload->UpDatePrgInfor())
			{
				return(4);
			}
			return(0);
	}	
	return(-1);
}

protocolmodbus::protocolmodbus(void)
	:protocols::protocol()
{
	mModbusRegPartitionsLen = 0;
	mFirmwaredownload = 0;
	SpeOrderCallBack = 0;
	RequestReportDataCallBack = 0;
	BroadCastCallBack = 0;
	BroadCastAddr = 0;
}

protocolmodbus::~protocolmodbus(void)
{

}
///> 对接收到的数据进行拆包，分解出地址，功能码，
bool protocolmodbus::Unpack(uint8_t *ucData, uint16_t usDataLen)
{
	uint16_t i,j;
	for(i = 0; i < usDataLen; i++)
	{
		if(usDataLen - i < 4)
		{
			return(false);
		}
		Function = (ModbusFunctionTPDF)ucData[i + 1];
		SlaveAddr = ucData[i];
		switch(Function)
		{
			case MODBUS_FUNCTION_READCOIL:
			case MODBUS_FUNCTION_READINPUT:
			case MODBUS_FUNCTION_READREG:
			case MODBUS_FUNCTION_READINPUTREG:
				RegisterAddr = (ucData[i + 2] << 8) + ucData[i + 3]; ///读地址
				DataLen = (ucData[i + 4] << 8) + ucData[i + 5];  //读地址长度
				if(Function == MODBUS_FUNCTION_READREG || Function == MODBUS_FUNCTION_READINPUTREG)
				{
					DataLen *= 2; //地址UINT16  DataLen 以字节为单位
				}
				j = dCrcCheck(&ucData[i],6);///校验数据
				if(j == ((ucData[i + 6] << 8) + ucData[i + 7]))
				{
					return(true);
				}
				break;
			case MODBUS_FUNCTION_WRITECOIL:
			case MODBUS_FUNCTION_WRITEREG: ///> 写寄存器一次只写2字节
				RegisterAddr = (ucData[i + 2] << 8) + ucData[i + 3]; ///>写地址
				Data[0] = ucData[i + 4];//> 写数据
				Data[1] = ucData[i + 5]; 
				DataLen = 2;            //写长度
				j = dCrcCheck(&ucData[i],6); // 校验
				if(j == ((ucData[i + 6] << 8) + ucData[i + 7]))
				{
					return(true);
				}
				break;
			case MODBUS_FUNCTION_WRITEMULTREG: ///多地址写
				RegisterAddr = (ucData[i + 2] << 8) + ucData[i + 3]; ///地址
				DataLen = ucData[i + 6]; //写长度
				j = dCrcCheck(&ucData[i],7 + ucData[i + 6]);
				if(j == ((ucData[i + DataLen + 7] << 8) + ucData[i + DataLen + 8]))
				{
					for(j = 0; j < DataLen; j++)
					{
						Data[j] = ucData[i + j + 7]; ///写数据据
					}
					return(true);
				}
				break;
			case MODBUS_FUNCTION_SLAVEREPORT: ///> 子设备反馈
				j = dCrcCheck(&ucData[i],2);
				if(j == ((ucData[i + 2] << 8) + ucData[i + 3]))
				{
					return(true);
				}
				break;
			default:
				break;
		}
	}
	return(false);
}

uint16_t protocolmodbus::Pack(uint8_t *ucData)
{
	unsigned char i;
	unsigned short usCrc;
	ucData[0] = SlaveAddr;
	ucData[1] = (uint8_t)Function;
	if(ErrorCode)
	{
		ucData[1] = Function | 0x80;
		ucData[2] = ErrorCode;
		usCrc = dCrcCheck(ucData,3);
		ucData[3] = (usCrc >> 8) & 0x00ff;
		ucData[4] = usCrc & 0x00ff;
		return(5);
	}
	else
	{
		switch(Function)
		{
			case MODBUS_FUNCTION_READCOIL:
			case MODBUS_FUNCTION_READINPUT:
			case MODBUS_FUNCTION_READREG:
			case MODBUS_FUNCTION_READINPUTREG:
			case MODBUS_FUNCTION_SLAVEREPORT:
				ucData[2] = DataLen & 0x00ff;
				for(i = 0; i < DataLen; i++)
				{
					ucData[3 + i] =  Data[i];
				}
				usCrc = dCrcCheck(ucData,i + 3);
				ucData[i + 3] = (usCrc >> 8) & 0x00ff;
				ucData[i + 4] = usCrc & 0x00ff;
				return(i + 5);
			case MODBUS_FUNCTION_WRITECOIL:
			case MODBUS_FUNCTION_WRITEREG:
		    	ucData[2] = (RegisterAddr >> 8) & 0x00ff;
		    	ucData[3] = RegisterAddr & 0x00ff;
		    	ucData[4] = Data[0];
		    	ucData[5] = Data[1];
		    	usCrc = dCrcCheck(ucData,6);
		    	ucData[6] = (usCrc >> 8) & 0x00ff;
		    	ucData[7] = usCrc & 0x00ff;
		    	return(8);
			case MODBUS_FUNCTION_WRITEMULTREG:
				ucData[2] = (RegisterAddr >> 8) & 0x00ff;
				ucData[3] = RegisterAddr & 0x00ff;
				ucData[4] = (DataLen >> 9) & 0x00ff;
				ucData[5] = (DataLen >> 1) & 0x00ff;
				usCrc = dCrcCheck(ucData,6);
				ucData[6] = (usCrc >> 8) & 0x00ff;
				ucData[7] = usCrc & 0x00ff;
				return(8);
		}
	}
	return(0);
}

void protocolmodbus::RegistePartitionTable(ModbusRegPartitionTPDF *tModbusRegPartitions, uint16_t usModbusRegPartitionsLen)
{
	mModbusRegPartitions = tModbusRegPartitions;
	mModbusRegPartitionsLen = usModbusRegPartitionsLen;
}

bool protocolmodbus::Map(protocolmodbus *tOutput, uint8_t ucSlaveAddr)
{
	uint16_t i;
	int8_t j;
	
	tOutput->SlaveAddr = ucSlaveAddr;
	tOutput->ErrorCode = 0;
	tOutput->Function = Function;
	tOutput->RegisterAddr = RegisterAddr;
	tOutput->DataLen = DataLen;
	tOutput->Data[0] = Data[0];
	tOutput->Data[1] = Data[1];
	
	if(SlaveAddr == BroadCastAddr)
	{
		if(!BroadCastCallBack)
		{
			return(false);
		}
		return(BroadCastCallBack(this));
	}
	else if(SlaveAddr != ucSlaveAddr)
	{
		return(false);
	}
	switch(Function)
	{
		case MODBUS_FUNCTION_READCOIL:
		case MODBUS_FUNCTION_READINPUT:
			break;
		case MODBUS_FUNCTION_READREG:
		case MODBUS_FUNCTION_READINPUTREG:
			if(DataLen > 240)
			{
				tOutput->ErrorCode = 2;
				return(true);
			}
			for(i = 0; i < mModbusRegPartitionsLen; i++)
			{
				if(RegisterAddr >= mModbusRegPartitions[i].RegisterStartAddr 
					&& (RegisterAddr + (DataLen >> 1)) <= ((mModbusRegPartitions[i].ResourceLen >> 1) + mModbusRegPartitions[i].RegisterStartAddr)
					&& (mModbusRegPartitions[i].RegisterReadWrite == REGISTER_READONLY || mModbusRegPartitions[i].RegisterReadWrite == REGISTER_READWRITE))
				{
					DataCopy(&mModbusRegPartitions[i], tOutput->Data);
					return(true);
				}
			}
			tOutput->ErrorCode = 2;
			return(true);
		case MODBUS_FUNCTION_WRITEREG:
		case MODBUS_FUNCTION_WRITECOIL:
			for(i = 0; i < mModbusRegPartitionsLen; i++)
			{
				if(RegisterAddr >= mModbusRegPartitions[i].RegisterStartAddr 
					&& (RegisterAddr) < ((mModbusRegPartitions[i].ResourceLen >> 1) + mModbusRegPartitions[i].RegisterStartAddr)
					&& (mModbusRegPartitions[i].RegisterReadWrite == REGISTER_WRITEONLY || mModbusRegPartitions[i].RegisterReadWrite == REGISTER_READWRITE))
				{
					if(mModbusRegPartitions[i].WriteOrderCallBack)
					{
						if(!DataCheckAndWriteDataParse(&mModbusRegPartitions[i]))
						{
							tOutput->ErrorCode = 3;
							return(true);
						}
						if(mModbusRegPartitions[i].WriteOrderCallBack(mWriteDataAttribute, usWriteDataAttributeLen))
						{
							return(true);
						}
						else
						{
							tOutput->ErrorCode = 4;
							return(true);
						}
					}
					else
					{
						tOutput->ErrorCode = 4;
						return(true);
					}
				}
			}
			tOutput->ErrorCode = 2;
			return(true);
		case MODBUS_FUNCTION_WRITEMULTREG:
			if(RegisterAddr == 0x0000) //特殊命令
			{
				j = BaseSpeOrderProcess(SlaveAddr, (Data[0] << 8) + Data[1], &Data[2], DataLen - 2);///代码下载流程
				if(j != -1)
				{
					tOutput->ErrorCode = j;
					return(true);
				}
				if(!SpeOrderCallBack)
				{
					tOutput->ErrorCode = 4;
					return(true);
				}
				if(SpeOrderCallBack(SlaveAddr, (Data[0] << 8) + Data[1], &Data[2], DataLen - 2))
				{
					return(true);
				}
				else
				{
					tOutput->ErrorCode = 3;
					return(true);
				}
			}
			for(i = 0; i < mModbusRegPartitionsLen; i++)
			{
				if(RegisterAddr >= mModbusRegPartitions[i].RegisterStartAddr 
					&& (RegisterAddr) < ((mModbusRegPartitions[i].ResourceLen >> 1) + mModbusRegPartitions[i].RegisterStartAddr)
					&& (mModbusRegPartitions[i].RegisterReadWrite == REGISTER_WRITEONLY || mModbusRegPartitions[i].RegisterReadWrite == REGISTER_READWRITE))
				{
					if(mModbusRegPartitions[i].WriteOrderCallBack)
					{
						if(!DataCheckAndWriteDataParse(&mModbusRegPartitions[i]))
						{
							tOutput->ErrorCode = 3;
							return(true);
						}
						if(mModbusRegPartitions[i].WriteOrderCallBack(mWriteDataAttribute, usWriteDataAttributeLen))
						{
							return(true);
						}
						else
						{
							tOutput->ErrorCode = 4;
							return(true);
						}
					}
					else
					{
						tOutput->ErrorCode = 4;
						return(true);
					}
				}
			}
			tOutput->ErrorCode = 2;
			return(true);
		case MODBUS_FUNCTION_SLAVEREPORT:
			if(RequestReportDataCallBack)
			{
				tOutput->DataLen = RequestReportDataCallBack(tOutput->Data);
				if(!tOutput->DataLen)
				{
					tOutput->ErrorCode = 3;
				}
				return(true);
			}
			tOutput->ErrorCode = 4;
			return(true);
		default:
			tOutput->ErrorCode = 1;
			return(false);
	}
	return(false);
}
